﻿#region

using System;
using System.Collections.Generic;
using DomainModel.Domain.Bases;
using DomainModel.Domain.Model.MessageAssemblyModel;
using DomainModel.Domain.Model.MessageTypeModel;
using DomainModel.Utils;
using Iesi.Collections.Generic;

#endregion

namespace DomainModel.Domain.Model.ServiceModel
{
    public class Service : Entity<Service, ServiceId>
    {
        public Service(ServiceId id) : base(id)
        {
            Validate.NotNull(id, "ServiceId must not be null");

            CreateModifyInfo = new CreateModifyInfo();
        }

        public virtual string Name { get; set; }
        public virtual string Summary { get; set; }
        public virtual string Version { get; set; }
        public virtual QueueInfo InputQueue { get; set; }
        public virtual QueueInfo ErrorQueue { get; set; }
        public virtual QueueInfo AuditQueue { get; set; }
        public virtual DateTime FirstSeen { get; set; }
        public virtual DateTime LastAlive { get; set; }
        public virtual DateTime LastStarted { get; set; }
        public virtual CreateModifyInfo CreateModifyInfo { get; set; }

        public virtual ISet<MessageAssembly> MessageAssembliesSet { get; set; }
        public virtual ISet<ServiceRole> ServiceRolesSet { get; set; }

        protected internal Service()
        {
        }

        public virtual void AddServiceRole(ServiceRole serviceRole)
        {
            if (serviceRole.Service != null)
            {
                throw new ArgumentException("Cannot add ServiceRole that is already assigned to a service");
            }

            serviceRole.Service = this;

            if (ServiceRolesSet == null)
            {
                ServiceRolesSet = new HashedSet<ServiceRole>();
            }

            ServiceRolesSet.Add(serviceRole);
        }

        public virtual void AddMessageAssembly(MessageAssembly messageAssembly)
        {
            if (MessageAssembliesSet == null)
            {
                MessageAssembliesSet = new HashedSet<MessageAssembly>();
            }

            MessageAssembliesSet.Add(messageAssembly);
        }

        public virtual MessageType FindMessageType(String messageAssemblyName, String typeName)
        {
            MessageAssembly messageAssembly = FindMessageAssembly(messageAssemblyName);

            if (messageAssembly == null)
            {
                return null;
            }

            return messageAssembly.FindMessageType(typeName);
        }

        public virtual MessageAssembly FindMessageAssembly(String messageAssemblyName)
        {
            foreach (var messageAssembly in MessageAssembliesSet)
            {
                if (messageAssembly.Name.Equals(messageAssemblyName))
                {
                    return messageAssembly;
                }
            }

            return null;
        }

        public virtual bool IsPublisher()
        {
            foreach (var serviceRole in ServiceRolesSet)
            {
                if (serviceRole is PublisherRole)
                {
                    return true;
                }
            }

            return false;
        }

        public virtual bool IsHandler()
        {
            foreach (var serviceRole in ServiceRolesSet)
            {
                if (serviceRole is HandlerRole)
                {
                    return true;
                }
            }

            return false;
        }

        public virtual bool IsSubscriber()
        {
            foreach (var serviceRole in ServiceRolesSet)
            {
                if (serviceRole is SubscriberRole)
                {
                    return true;
                }
            }

            return false;
        }

        public virtual IList<MessageType> GetHandledMessageTypes()
        {

            IList<MessageType> handledMessageTypes = new List<MessageType>();

            foreach (var serviceRole in ServiceRolesSet)
            {
                if (serviceRole is HandlerRole)
                {
                    HandlerRole handlerRole = (HandlerRole) serviceRole;
                    handledMessageTypes.Add(handlerRole.HandledType);
                }
            }

            return handledMessageTypes;
        }

        public virtual string GetFriendlyName()
        {
            if (!string.IsNullOrEmpty(Name))
            {
                return Name;
            }

            return InputQueue.Address;

        }
    }
}